home *** CD-ROM | disk | FTP | other *** search
- #include <stdlib.h>
- #include <stdio.h>
- #include <stdarg.h>
- #include <time.h>
- #include <ctype.h>
- #include <string.h>
- #include "global.h"
- #include "timer.h"
- #include "cmdparse.h"
- #include "netuser.h"
- #include "nntp.h"
- #include "smtp.h"
- #include "domain.h"
- #include "misc.h"
- #include "tcp.h"
- #include "mbuf.h"
- #include "reader.h"
- #include "flex.h"
- #include "os.h"
- #include "swis.h"
-
- struct nntpservers *Nntpservers = NULLNNTP;
-
- static void nntptick(void *);
- static void make_got_table(int, void *);
- static int doadds(int, char **);
- static int dodrops(int, char **);
- static int dokicks(int, char **);
- static int dostop(int, char **);
- static void quit(struct nntpservers *, BOOL);
- static void nntp_rec(struct tcb *, int16);
- static void nntp_cts(struct tcb *, int16);
- static void nntp_state(struct tcb *, char, char);
- static void sendit(struct nntpservers *, char *, ...);
-
- extern int16 lport; /* local port placeholder */
-
- static char quitcmd[] = "QUIT\r\n";
-
- struct cmds nntpcmds[] = {
- "addserver", doadds, 4, "nntp addserver <name> <time> <abbr>", NULLCHAR,
- "dropserver", dodrops, 2, "nntp dropserver <name|abbr>", NULLCHAR,
- "kick", dokicks, 2, "nntp kick <name|abbr>", NULLCHAR,
- "stop", dostop, 0, "nntp stop <name|abbr>", NULLCHAR,
- NULLCHAR,
- };
-
- int donntp(int argc, char **argv)
- {
- return subcmd(nntpcmds,argc,argv);
- }
-
- static int doadds(int argc, char *argv[])
- {
- struct nntpservers *np;
- int lh, ll, hh, hl;
- int i;
-
- for(np = Nntpservers; np != NULLNNTP; np = np->next)
- if (stricmp(np->name, argv[1]) == 0)
- break;
-
- if (np == NULLNNTP)
- {
- np = (struct nntpservers *) calloc(1,sizeof(struct nntpservers));
- np->name = strdup(argv[1]);
- np->abbr = strdup(argv[3]);
- np->ipdest = resolve(argv[1]);
- np->next = Nntpservers;
- Nntpservers = np;
- np->lowtime = np->hightime = -1;
- np->nntpcli_t.func = nntptick; /* what to call on timeout */
- np->nntpcli_t.arg = (void *)np;
- np->rfile = NULLFILE;
- np->sfile = NULLFILE;
- np->tfile = NULLFILE;
- np->got_table = NULL;
- }
-
- if (argc > 4)
- {
- for (i = 4; i < argc; ++i)
- {
- if (isdigit(*argv[i]))
- {
- sscanf(argv[i], "%d:%d-%d:%d", &lh, &ll, &hh, &hl);
- np->lowtime = lh * 100 + ll;
- np->hightime = hh * 100 + hl;
- }
- }
- }
-
- /* set timer duration */
- set_timer(&np->nntpcli_t, atol(argv[2]) * 1000L);
- start_timer(&np->nntpcli_t); /* and fire it up */
-
- make_got_table(0, (void *)np);
-
- return 0;
- }
-
- static int dodrops(int argc, char *argv[])
- {
- struct nntpservers *np, *npprev = NULLNNTP;
-
- argc = argc;
-
- for(np = Nntpservers; np != NULLNNTP; npprev = np, np = np->next)
- {
- if (stricmp(np->name, argv[1]) == 0 ||
- stricmp(np->abbr, argv[1]) == 0)
- {
- stop_timer(&np->nntpcli_t);
- free(np->name);
- free(np->abbr);
- if (np->rfile != NULLFILE) fclose(np->rfile);
- if (np->sfile != NULLFILE) fclose(np->sfile);
- if (np->tfile != NULLFILE) fclose(np->tfile);
- if (np->got_table != NULL)
- {
- flex_free((flex_ptr) &(np->got_table));
- np->got_table = NULL;
- np->msg_tot = 0;
- }
- if(npprev != NULLNNTP)
- npprev->next = np->next;
- else
- Nntpservers = np->next;
- free((char *)np);
- return 0;
- }
- }
-
- return 0;
- }
-
- static int dokicks(int argc, char *argv[])
- {
- struct nntpservers *np;
-
- argc = argc;
-
- for(np = Nntpservers; np != NULLNNTP; np = np->next)
- {
- if (stricmp(np->name, argv[1]) == 0 ||
- stricmp(np->abbr, argv[1]) == 0)
- {
- /* If the timer is not running, the timeout function has
- * already been called and we don't want to call it again.
- */
- if(run_timer(&np->nntpcli_t))
- {
- np->state = NN_INIT_STATE;
- np->stage = NN_INIT_STAGE;
- stop_timer(&np->nntpcli_t);
- nntptick((void *)np);
- }
-
- return 0;
- }
- }
-
- return 0;
- }
-
- static int dostop(int argc, char *argv[])
- {
- struct nntpservers *np;
-
- argc = argc;
-
- for(np = Nntpservers; np != NULLNNTP; np = np->next)
- {
- if (stricmp(np->name, argv[1]) == 0 ||
- stricmp(np->abbr, argv[1]) == 0)
- {
- quit(np, FALSE);
- start_timer(&np->nntpcli_t);
- return 0;
- }
- }
-
- return 0;
- }
-
- static void make_got_table(int at, void *handle)
- {
- char buffer[256];
- int loop;
- static long file_len;
- message_data temp;
- struct nntpservers *cb;
-
- at = at;
- cb = (struct nntpservers *) handle;
-
- if (cb->got_table == NULL)
- {
- cb->msg_tot = 0;
- if (!flex_alloc((flex_ptr) &(cb->got_table), ID_LEN))
- return;
- }
-
- if (cb->id_file == NULLFILE)
- {
- sprintf(buffer, "<ReadBack$Dir>.%sMail", cb->abbr);
- if ((cb->id_file = fopen(buffer, "r")) != NULLFILE)
- {
- fseek(cb->id_file, 0, SEEK_END);
- file_len = ftell(cb->id_file);
- fseek(cb->id_file, 9, SEEK_SET);
- }
- else
- {
- return;
- }
- }
-
- if (ftell(cb->id_file) < file_len)
- {
- if (flex_extend((flex_ptr) &(cb->got_table), (cb->msg_tot + 5) * ID_LEN))
- {
- for (loop = 0; loop < 5 && ftell(cb->id_file) < file_len; loop++)
- {
- fread(&temp, sizeof(message_data), 1, cb->id_file);
- fgets(buffer, 250, cb->id_file);
- fgets(buffer, 250, cb->id_file);
- strncpy((cb->got_table)[cb->msg_tot], buffer, ID_LEN);
- (cb->got_table)[cb->msg_tot][ID_LEN - 1] = '\0';
- rip((cb->got_table)[cb->msg_tot]);
- fseek(cb->id_file, temp.comp_bytes + 4L, SEEK_CUR);
- cb->msg_tot++;
- }
- }
- }
- else
- {
- fclose(cb->id_file);
- cb->id_file = NULLFILE;
- return;
- }
-
- alarm_set(alarm_timenow() + 2, make_got_table, (void *)cb);
- }
-
- void nntptick(void *tp)
- {
- struct socket lsocket, fsocket;
- register struct nntpservers *cb;
-
- cb = (struct nntpservers *)tp;
-
- if (cb == NULLNNTP) return;
-
- if (cb->state != NN_INIT_STATE) return;
-
- /* setup the socket */
- fsocket.address = cb->ipdest;
- fsocket.port = NNTP_PORT;
-
- lsocket.address = ip_addr; /* our ip address */
- lsocket.port = lport++; /* next unused port */
-
- /* open nntp connection */
- cb->stage = NN_OPEN_STAGE; /* init stage placeholder */
- cb->state = NN_OPEN_STATE; /* init state placeholder */
-
- cb->tcb = open_tcp(&lsocket,&fsocket,TCP_ACTIVE,tcp_window,
- (void(*)())nntp_rec,(void(*)())nntp_cts,(void(*)())nntp_state,0,(char *)cb);
-
- cb->tcb->user = (char *)cb; /* Upward pointer */
-
- start_timer(&cb->nntpcli_t); /* restart the timer */
- }
-
- static BOOL have_we(char *line, struct nntpservers *cb)
- {
- int loop = 0;
- char buffer[NNTPMAXLEN];
-
- strcpy(buffer, line);
-
- if (cb->msg_tot == 0) return(FALSE);
- rip(buffer);
- buffer[strlen(buffer) - 1] = '\0';
-
- while (loop < cb->msg_tot && strncmp(&buffer[1], (cb->got_table)[loop], ID_LEN) != 0)
- loop++;
-
- if (loop < cb->msg_tot) return(TRUE);
-
- if (flex_extend((flex_ptr) &(cb->got_table), (cb->msg_tot + 1) * ID_LEN))
- {
- strncpy((cb->got_table)[cb->msg_tot], buffer, ID_LEN);
- (cb->got_table)[cb->msg_tot][ID_LEN - 1] = '\0';
- cb->msg_tot++;
- }
-
- return(FALSE);
- }
-
- void nntp_transaction(register struct nntpservers *cb)
- {
- register char reply;
- int rcode;
- char line[NNTPMAXLEN + 1], buffer[256];
- static char now[10], date[10], hour[10];
- FILE *temp;
-
- /* Another line follows; ignore this one */
- /* if(cb->buf[0] == '0') return; */
-
- reply = cb->buf[0];
- rcode = atoi(cb->buf);
-
- /* if service shuting down */
- if (cb->state == NN_OPEN_STATE && rcode == 400)
- {
- quit(cb, FALSE);
- return;
- }
- else if (cb->state == NN_OPEN_STATE && rcode == 411) /* No such group */
- {
- cb->state = NN_DATA_STATE;
- cb->buf[0] = '.';
- cb->buf[1] = '\n';
- cb->buf[2] = '\0';
- cb->stage = NN_NEWG_STAGE;
- }
- else if (cb->state == NN_OPEN_STATE && rcode == 430) /* No such Article */
- {
- cb->state = NN_DATA_STATE;
- cb->buf[0] = '.';
- cb->buf[1] = '\n';
- cb->buf[2] = '\0';
- cb->stage = NN_NEWN_STAGE;
- }
-
- switch(cb->state)
- {
- case NN_OPEN_STATE:
- if (reply == '5') quit(cb, FALSE);
- else if (reply == '2')
- {
- switch(cb->stage)
- {
- case NN_OPEN_STAGE:
- cb->stage = NN_NEWG_STAGE;
- now[0] = 3;
- os_word(14, now);
-
- sprintf(buffer, "<NETLITE$Dir>.%sLast", cb->abbr);
- if ((temp = fopen(buffer, "r")) != NULL)
- {
- if (fgets(date, 10, temp) == NULL)
- os_swi4(OS_ConvertDateAndTime, (int) now, (int) date, 10, (int) "%YR%MN01");
- if (fgets(hour, 10, temp) == NULL)
- strcpy(hour, "000001");
- fclose(temp);
- }
- else
- {
- os_swi4(OS_ConvertDateAndTime, (int) now, (int) date, 10, (int) "%YR%MN01");
- strcpy(hour, "000001");
- }
- rip(date);
- rip(hour);
- sendit(cb,"NEWGROUPS %s %s\r\n", date, hour);
- break;
- case NN_NEWG_STAGE:
- cb->state = NN_DATA_STATE;
- sprintf(buffer, "<Mail$Dir>.Folder.%sNG", cb->abbr);
- cb->tfile = fopen(buffer, "a");
- break;
- case NN_NEWN_STAGE:
- cb->state = NN_DATA_STATE;
- sprintf(buffer, "<NETLITE$Dir>.%sNew", cb->abbr);
- cb->tfile = fopen(buffer, "w");
- break;
- case NN_GETN_STAGE:
- cb->state = NN_DATA_STATE;
- cb->stage = NN_NEWN_STAGE;
- sprintf(buffer, "<Mail$Dir>.Folder.%sNews", cb->abbr);
- cb->tfile = fopen(buffer, "a");
- fprintf(cb->tfile, "#! rnews\n");
- break;
- }
- }
- break;
-
- case NN_DATA_STATE:
- tcp_output(cb->tcb); /* Send ACK; disk I/O is slow */
- if (cb->buf[0] == '.' &&
- cb->buf[1] == '\n' &&
- cb->buf[2] == '\0')
- {
- cb->state = NN_OPEN_STATE;
- if (cb->tfile != NULLFILE)
- {
- fclose(cb->tfile);
- cb->tfile = NULLFILE;
- }
-
- if (cb->stage == NN_NEWN_STAGE)
- {
- if (!cb->rfile)
- {
- sprintf(buffer, "<NETLITE$Dir>.%sNew", cb->abbr);
- cb->rfile = fopen(buffer, "r");
- }
-
- if (cb->rfile)
- {
- while(fgets(line, NNTPMAXLEN - 1, cb->rfile) != NULL && have_we(line, cb));
-
- if (!feof(cb->rfile))
- {
- rip(line);
- sendit(cb, "ARTICLE %s\r\n", line);
- cb->stage = NN_GETN_STAGE;
- }
- else
- {
- fclose(cb->rfile);
- cb->rfile = NULLFILE;
- sprintf(buffer, "<NETLITE$Dir>.%sNew", cb->abbr);
- remove(buffer);
- cb->stage = NN_NEWG_STAGE;
- }
- }
- }
-
- if (cb->stage == NN_NEWG_STAGE)
- {
- if (!cb->sfile)
- {
- sprintf(buffer, "<NETLITE$Dir>.%sGroup", cb->abbr);
- cb->sfile = fopen(buffer, "r");
- }
-
- if (cb->sfile != NULL)
- {
- if (fgets(line, NNTPMAXLEN - 25, cb->sfile) != NULL)
- {
- rip(line);
- sendit(cb,"NEWNEWS %s %s %s\r\n", line, date, hour);
- cb->stage = NN_NEWN_STAGE;
- }
- else
- {
- fclose(cb->sfile);
- cb->sfile = NULLFILE;
-
- sprintf(buffer, "<NETLITE$Dir>.%sLast", cb->abbr);
- if ((temp = fopen(buffer, "w")) != NULL)
- {
- os_swi4(OS_ConvertDateAndTime, (int)now, (int)date, 10, (int)"%YR%MN%DY");
- os_swi4(OS_ConvertDateAndTime, (int)now, (int)hour, 10, (int)"%24%MI%SE");
- fprintf(temp, "%s\n%s\n", date, hour);
- fclose(temp);
- }
- cb->state = NN_QUIT_STATE;
- quit(cb, TRUE);
- }
- }
- else
- {
- quit(cb, FALSE);
- }
- }
- }
- else
- {
- /* Append to data file - JSN 28/03/93 */
- if (strcmp(cb->buf, "..", 2) == 0)
- {
- if (fprintf(cb->tfile, cb->buf + 1) < 0)
- {
- cb->state = NN_OPEN_STATE;
- tprintf(cb->tcb, "File write error\n");
- }
- }
- else
- {
- if (fprintf(cb->tfile, cb->buf) < 0)
- {
- cb->state = NN_OPEN_STATE;
- tprintf(cb->tcb, "File write error\n");
- }
- }
- }
- break;
- }
- }
-
- /* close down link after a failure */
- static void quit(struct nntpservers *cb, BOOL normal)
- {
- cb->state = NN_QUIT_STATE;
- sendit(cb, quitcmd); /* issue a quit command */
- close_tcp(cb->tcb); /* close up connection */
-
- if (cb->rfile != NULLFILE) fclose(cb->rfile);
- if (cb->sfile != NULLFILE) fclose(cb->sfile);
- if (cb->tfile != NULLFILE) fclose(cb->tfile);
-
- cb->rfile = NULLFILE;
- cb->sfile = NULLFILE;
- cb->tfile = NULLFILE;
-
- start_timer(&cb->nntpcli_t);
- }
-
- /* nntp receiver upcall routine. fires up the state machine to parse input */
- static void nntp_rec(struct tcb *tcb, int16 cnt)
- {
- register struct nntpservers *cb;
- char c;
- struct mbuf *bp;
-
- if ((cb = (struct nntpservers *)tcb->user) == NULL) /* point to our struct */
- {
- close_tcp(tcb);
- return;
- }
-
- recv_tcp(tcb, &bp, cnt); /* suck up chars from low level routine */
-
- /* Assemble input line in buffer, return if incomplete */
- while (pullup(&bp, &c, 1) == 1)
- {
- switch (c)
- {
- case '\r': /* strip cr's */
- continue;
- case '\n': /* line is finished, go do it! */
- cb->buf[cb->cnt++] = '\n';
- cb->buf[cb->cnt] = '\0';
- nntp_transaction(cb);
- cb->cnt = 0;
- break;
- default: /* other chars get added to buffer */
- cb->buf[cb->cnt++] = c;
- if (cb->cnt > NNTPMAXLEN - 2)
- {
- cb->buf[cb->cnt] = '\0';
- nntp_transaction(cb);
- cb->cnt = 0;
- }
- break;
- }
- }
- }
-
- /* nntp transmitter ready upcall routine. twiddles cts flag */
- static void nntp_cts(struct tcb *tcb, int16 cnt)
- {
- register struct nntpservers *cb;
-
- cb = (struct nntpservers *)tcb->user; /* point to our struct */
-
- /* don't do anything until/unless we're supposed to be sending */
- if(cb->cts == 0) return;
- }
-
- /* nntp state change upcall routine. */
- static void nntp_state(register struct tcb *tcb, char old, char new)
- {
- register struct nntpservers *cb;
-
- old = old;
-
- cb = (struct nntpservers *)tcb->user;
-
- switch(new)
- {
- case ESTABLISHED:
- cb->state = NN_OPEN_STATE;/* shouldn't be needed */
- break;
- case CLOSE_WAIT:
- close_tcp(tcb); /* shut things down */
- break;
- case CLOSED:
- /* if this close was not done by us ie. a RST */
- if(cb->tfile != NULLFILE) fclose(cb->tfile);
- /* del_session(cb); */
- del_tcp(tcb);
- break;
- default:
- break;
- }
- }
-
- /* Send message back to server */
- static void sendit(struct nntpservers *cb, char *fmt, ...)
- {
- va_list argptr;
- struct mbuf *bp;
- char tmpstring[256];
-
- va_start(argptr,fmt);
- vsprintf(tmpstring,fmt,argptr);
- va_end(argptr);
-
- bp = qdata(tmpstring, (int16)strlen(tmpstring));
- send_tcp(cb->tcb, bp);
- }
-
-